const exec = require('child_process').exec;
const fs = require('fs');
const hdCompConfs = require('./hdCompileConfs');

//const path = require('path');
//const uuid = require('node-uuid');
/**
command:
arduino_debug --pref build.path=./build -v --verify ./Blink.ino
arguments and default values:
*/
var defaultConfig = {
    'command': null, // ('arduino' or 'arduion_debug' on windows),
    'rootBuildPath': null, // must set
    'verbose': false
}
var config = {};
var currentSerial = 0;

function postSrcToHex(req, res) {
    var code = req.body.code;
    if (code.length > 10 * 1024 * 1024) {
        res.setHeader('Content-Type', 'application/json');
        res.send(JSON.stringify({
            result: -1,
            msg: "文件大小超过限制，上限为10MB"
        }));
        return;
    }
    const dirPath = `${config.rootBuildPath}/${currentSerial++}/`;
    const buildPath = `${dirPath}build/`;
    const filePath = `${dirPath}code.ino`;
    console.log("文件路径：" + dirPath);
    if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath);
        fs.mkdirSync(buildPath);
    }

    fs.writeFile(filePath, code, function (error) {
        if (error) {
            console.error("代码写入文件出错" + error);
            res.send(JSON.stringify({
                result: -1,
                msg: "代码写入文件出错"
            }));
            return;
        }
        console.log("文件写入成功");
        // const cmd = config.command +
        //     " --pref build.path=" + buildPath +
        //     (config.verbose ? " --verbose-build " : "") +
        //     " --verify " + filePath;
        var hdCompConf = hdCompConfs[req.body.hdDataId];
        const fqbn = hdCompConf ? hdCompConf.arch : "arduino:avr:uno";
        const prefs = hdCompConf ? hdCompConf.prefs : "";
        const vidPid = ""; //先不写
        const cmd = `${config.command} -compile -logger=machine ${config.hardware} ${config.tools} ${config.builtinlibraries} ${config.libraries} -fqbn=${fqbn} ${vidPid} -ide-version=10809 -build-path ${buildPath} -warnings=none ${prefs} -verbose=false  ${filePath}`;
        console.log("编译代码命令:" + cmd);
        // cmd = `"C:\\Program Files (x86)\\Arduino\\arduino-builder" -compile -logger=machine -hardware "C:\\Program Files (x86)\\Arduino\\hardware" -hardware "C:\\Users\\AaronChan\\AppData\\Local\\Arduino15\\packages" -tools "C:\\Program Files (x86)\\Arduino\\tools-builder" -tools "C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr" -tools "C:\\Users\\AaronChan\\AppData\\Local\\Arduino15\\packages" -built-in-libraries "C:\\Program Files (x86)\\Arduino\\libraries" -libraries C:\\Users\\AaronChan\\Documents\\Arduino\\libraries -fqbn=esp8266:esp8266:nodemcuv2:CpuFrequency=80,UploadSpeed=115200,FlashSize=4M3M -ide-version=10801 -build-path ${buildPath} -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.xtensa-lx106-elf-gcc.path="C:\\Users\\AaronChan\\AppData\\Local\\Arduino15\\packages\\esp8266\\tools\\xtensa-lx106-elf-gcc\\1.20.0-26-gb404fb9-2" -prefs=runtime.tools.esptool.path=C:\\Users\\AaronChan\\AppData\\Local\\Arduino15\\packages\\esp8266\\tools\\esptool\\0.4.9 -prefs=runtime.tools.mkspiffs.path=C:\\Users\\AaronChan\\AppData\\Local\\Arduino15\\packages\\esp8266\\tools\\mkspiffs\\0.1.2 -verbose ${filePath}`;       
        var subProc = exec(cmd, (error, stdout, stderr) => {
            if (error) {
                console.error(`exec error文件编译出错: ${error}`);
                res.send(JSON.stringify({
                    result: -1,
                    msg: "文件编译出错"
                }));
                return;
            }
            console.log(`stdout: ${stdout}`);
            console.log(`stderr: ${stderr}`);
            const postfix = hdCompConf ? hdCompConf.postfix : "hex";
            const buildFilePath = `${buildPath}code.ino.${postfix}`;
            const buildFilePath2 = `${buildPath}code.ino.partitions.${postfix}`;
            console.log("编译路径：\n" + buildFilePath + "\n" + buildFilePath2);
            fs.readFile(buildFilePath, function (error, bytesRead) {
                if (error) {
                    console.error('exec error读取编译完成的文件出错');
                    console.error(error);
                    res.send(JSON.stringify({
                        result: -1,
                        msg: "读取编译完成的文件出错"
                    }));

                } else {
                    fs.stat(buildFilePath2, function (error2, stats) {
                        if (error2) {
                            console.error(`exec error读取编译完成的文件出错,可能是文件${buildFilePath2}不存在`);
                            console.error(error2);
                            const buf = Buffer.from(bytesRead).toString('base64');
                            res.send(JSON.stringify({
                                result: 0,
                                // code: bytesRead
                                code: buf
                            }));
                            removeBuildFile();

                        } else {
                            if (stats.isFile()) {
                                fs.readFile(buildFilePath2, function (error3, bytesRead2) {
                                    if (error3) {
                                        console.error('exec error读取编译完成的文件出错3');
                                        console.error(error3);
                                        res.send(JSON.stringify({
                                            result: -1,
                                            msg: "读取编译完成的文件出错"
                                        }));

                                    } else {
                                        // console.log(bytesRead.length + "********************");
                                        // console.log(bytesRead2.length + "*******************");
                                        const buf = Buffer.from(bytesRead).toString('base64');
                                        const buf2 = Buffer.from(bytesRead2).toString('base64');
                                        res.send(JSON.stringify({
                                            result: 0,
                                            // code: bytesRead,
                                            // code2: bytesRead2
                                            code: buf,
                                            code2: buf2
                                        }));
                                        removeBuildFile();
                                    }

                                });
                            } else {
                                const buf = Buffer.from(bytesRead).toString('base64');
                                res.send(JSON.stringify({
                                    result: 0,
                                    // code: bytesRead
                                    code: buf
                                }));
                                removeBuildFile();
                            }
                        }
                    });
                }
            });
        });
    });
    //删除编译文件
    var removeBuildFile = function () {
        const rmfile = process.platform === 'win32' ? `RD /S /Q "${dirPath}"` : `rm -rf "${dirPath}"`;
        exec(rmfile, (error, stdout, stderr) => {
            if (error) {
                console.error(rmfile + "删除文件夹出错" + error);
            } else {
                console.log("删除文件夹成功" + dirPath);
            }
        });
    };
}
exports.initApp = function (_config, app) {
    // defaultConfig.command = process.platform === 'win32' ? 'arduino_debug' : 'arduino';     
    Object.assign(config, defaultConfig);
    Object.assign(config, _config);
    console.log(config);
    for (var key in hdCompConfs) {
        var hcf = hdCompConfs[key];
        hcf.prefs = hcf.prefs.replace(/{arduinoPath}/g, config.arduinoPath);
        hcf.prefs = hcf.prefs.replace(/{thirdPartyPath}/g, config.thirdPartyPath);
    }
    app.post("/compiler/ardunio", postSrcToHex);
}